查看原文
其他

线上大爆发,移动订单量占比达83%,归功于苏宁易购移动端统一接入层!

2017-06-20 任良成、王一硼 51CTO技术栈

近几年,苏宁易购随着业务的发展,用户使用习惯的改变,不断强化移动端发展,加强与视频直播,娱乐、体育营销等各类内容媒体的合作,创新营销产品,不断提升移动端日活,2017 年 3 月移动端订单数量已占线上整体比例的 83%。


为了进一步提高移动端访问速度,提升用户体验,移动团队潜心研究网关、http2.0技术,最终决定上线统一接入层。


下面从三个方面解析苏宁易购移动端统一接入层:


  • 统一接入层设计

  • 统一接入层的功能、实现

  • 统一接入层的性能


统一接入层的设计


苏宁易购的架构演进


苏宁易购的网络架构不断发展演进,2014 年接入应用防火墙,为 Web 应用提供安全保护。2015 - 2016 年,整体架构更加健壮稳定,保障了业务需求,支撑了线上业务的飞速发展。


2017 年,随着统一接入层的加入,系统封装了应用程序的内部结构。客户端只需要同网关交互,而不必调用特定的服务。并在此基础上,系统做了域名收敛,使用 http2.0 协议,重点提高了移动端的访问速度。


统一接入层的架构划分


统一接入层的架构划分图


统一接入层内部架构分为三层:

  • 代理层,有多台代理 proxy,由 go 语言实现,将请求向后转发;

  • 一个个虚拟的集群,每个集群对应一个业务系统,并且管理着系统的服务器;

  • 服务器,该服务器为目前线上各个系统的服务器。配置信息存储在 zookeeper 上,后台管理系统对 zookeeper 上的配置数据进行统一的管理。

统一接入层内部架构图


从上往下,统一接入层对移动端的请求做了接管,然后转发到相应的服务器上去。代理层用 go 语言实现,主要是利用 go 的高性能,以及线程无限制。后台管理系统使用 Java 实现,为了统一管理,使用公司内部 passport、统一后台管理等。

统一接入层内部组件图


目前,移动端系统接入统一接入层后,iOS 和 Android 客户端发出的请求全部收敛为一个域名,并且走 http2.0 协议。请求经 CDN 到达代理层 proxy,proxy 再将请求转发到各个集群系统,回源协议支持 http2.0,http1.1。

统一接入层网络架构


统一接入层功能、实现


统一接入层的一项重要功能是转发请求,我们首先考虑基于 Nginx 做整个代理层,但综合分析,其与我们团队技术方向不一致,修改 Nginx 成本较高,不便于定制个性化需求。


然后,我们选择使用 go 语言,一是被其简洁的语法所吸引,二是其性能确实强悍,后期的压测数据,也证实了这一点,让我们感到惊喜。


技术实现方案

下面介绍在整个实现过程中,我们应用的技术点,和接入层具备的功能:


  • 采用高效的 fasthttp 组件做请求接入和转发层,性能直逼 Ngnix,经过测试每个转发请求包括网络传输平均只增加了 0.1 毫秒。

    fasthttp是 Go 的一款不同于标准库 net/http 的 HTTP 实现,其性能可以达到标准库的 10 倍。

  • 在匹配路由规则上,通过快速查找算法和精准匹配算法的互补,可以既保证性能又保证准确性。

  • 在对后端请求的转发上,使用 TCP 链路复用的方式,使得请求在转发层面上犹如同一台机器,大量的减少网络交互。

  • 对于后端服务的检活,是用主动检活加被动检活相结合的方式,提高了对后端服务快速容错的能力。

  • 所有的规则配置通过 zookeeper 快速配置,可以实现线上配置实时生效的功能。

  • 对于内部组件 filter 层,使用的 go 1.8 支持的 plugin 的方式,通过线上动态打补丁的方式来支持新需求的功能增加。

  • 整个 proxy 基本是无状态的,对 zookeeper 部署上也考虑了多机房同步的方案,所以整个统一接入层也具备多机房部署能力。

  • 支持修改请求的 HOST,统一接入层修改了请求的域名,但一些系统的 Apache 上针对原域名有配置,尤其是需要登录的接口。

    为应对这一点,支持在后台配置请求的原始域名,proxy 转发时,HOST 的值为原始域名,这样一来,请求就能正确的响应,并且原系统不需要修改服务器配置,对接入层无感知。


转发规则动态配置

所有配置数据(转发规则)存放在 zookeeper 上,支持动态配置,由后台管理系统统一管理。


  • 代理(proxy),代理机器在 zookeeper 注册临时节点,如果代理机器与 zookeeper 的连接断开,临时节点自动删除,利用临时节点的特性检活 proxy。

  • 转发规则(api),存放的是 url 的路由规则,如下图,统一接入层根据url转发,将匹配 / mtspre /* 的请求,转发到集群 mtspre,并且重写转发后的请求地址。

转发规则


  • 集群(cluster),存放每个集群的信息,集群中包含的服务器和转发策略,支持随机和哈希两种方式。

集群信息


  • 服务器(server),存放所有服务器的信息,包括检活周期和超时时间。

  • 绑定关系(bind),存放集群和服务器的绑定关系。


proxy 代理层监听 zookeeper 的每一个节点,一旦节点数据发生变化,可以实时的获取最新的配置,立即生效,改变请求的路由策略。


为了保证可靠性,应对 zookeeper 所在的虚拟机宕机,所有配置信息入库,并且写文件,极端情况下,proxy可以从文件中读取配置信息,正常启动。


协议

移动端发出的请求统一走 http2.0 协议,Android 端使用 okhttp 实现,iOS 端使用 AFNetworking。


相比 HTTP/1.x,HTTP/2,系统在底层传输做了很大的改动和优化:


  • HTTP/2 采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。

  • HTTP/2 对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络流量。而 HTTP/1.x 每次请求,都会携带大量冗余头信息,浪费了很多带宽资源。

  • 多路复用,直白的说就是所有的请求都是通过一个 TCP 连接并发完成。同时,流还支持优先级和流量控制。

  • Server Push:服务端能够更快的把资源推送给客户端。例如服务端可以主动把 JS 和 CSS 文件推送给客户端。


HTTP/2 主要是 HTTP/1.x 在底层传输机制上的完全重构,HTTP/2 是基本兼容 HTTP/1.x 的语义。Content-Type 仍然是 Content-Type,只不过它不再是文本传输了。


域名收敛

接入统一接入层后,客户端使用到的域名都收敛成一个域名,域名后面的第一个目录,标记了该请求所属的系统,即路由规则,程序员据此将请求转发到不同的系统。客户端收敛域名,不仅有效的减少首次访问的DNS解析次数,最主要的是为了充分利用 http2.0 的特性——多路复用。


因为只有一个域名,所有请求只需要建立一条连接即可发送完毕,大大减少等待时间,真正实现并发。如下图所示的链路复用,只进行了一次 ssl 握手(紫色部分),其他请求复用此链路,并且同时发出。

后端服务器检活

做请求转发,检查后端 server 的健康性非常重要,我们目前有两套检活方案,同时运行。


(1)前台代理层 proxy 被动检活


proxy 向后端服务器转发请求,如果返回失败,则将这台服务器的 checkFailCount 加1,checkFailCount 超过 3,就会将服务器标记为 down,不再向它发起转发请求。默认检活超时是 3s,3s 之内,后端 server 没有再次返回失败,将 checkFailCount 清零。


(2)后台管理系统主动检活


后台主动检活,在后台管理系统启动时便开始运行,可以设置检活周期和超时时间。检活线程根据服务器的 IP 及端口号,主动与每一台服务器建立 socket 连接,建立连接超时则认为服务器不可用,将其状态标记为 down;成功建立连接,则将状态标记为 up。


前后主动、被动检活的结合,保证了在服务器不可用的时候,停止向其转发请求。同时,在服务器重新可用时,将其状态标记为up,前台proxy可以继续向其转发请求。


开关

(1)降级开关


为了保证可靠性,统一接入层修改了原有的网络链路,上线必须有降级开关。目前,我们设计了一套开关,可以针对 APP 版本号,以及操作系统类型设置开关的状态。


开关打开时,将原域名转换成收敛后的域名,请求走统一接入层;关闭开关,域名恢复成原域名,请求不经过统一接入层,直接走原链路,支持线上实时切换。


(2)协议转换开关


http2.0 的应用还在起步阶段,目前网络链路上存在一定的风险,这是我们所不能接受的,为此设计了另外一套开关,可以将协议在 http2.0 和 http1.1 之间切换,将风险降低到最低。


统一接入层性能


系统性能

为了测试统一接入层的性能,能否达到上线要求。移动团队对苏宁易购 APP 端的生产接口进行了压测,场景 1 是请求走原始链路,场景 2 是请求经过统一接入层,压测数据如下。

原始链路请求

统一接入层转发请求


请求走原始链路,平均 tps 为 9130,平均响应时间是 11 ms,通过统一接入层的请求,tps 达到 14200,提高了 50%,响应时间 6ms,缩短了近一半。这得益于 go 语言的高性能,快速路由选择算法,以及后端 tcp 连接的复用。


真实用户数据采集

为了提高系统的访问性能,也为了检验统一接入层在实际生产环境中的表现,我们将部分接口接入了统一接入层,运行到生产环境中,经过不间断的监控,我们采集到了真实的用户数据。


未接入统一接入层的接口,请求数据:

原始链路接口


接入统一接入层的接口,请求数据:

接入统一接入层的接口


图 1 为原始链路接口的 top99,71% 的请求平均响应时间为 72ms,图 2 是接入统一接入层的接口,域名收敛,协议走 http2.0,然后经过系统的 proxy 转发,87% 的请求平均响应时间为 62ms,top99 数据有明显的提高。


结语


本文主要分享了统一接入层的技术实现方案和功能,利用 go 语言的快速、高效、高性能,搭上 http2.0 的快车,为用户提供更好的购物体验。上线以来,通过 24 小时不间断监控和采集数据,统一接入层功能稳定,性能提升了 20% 左右,达到了我们的预期。


但是,目前统一接入层处于起步阶段,移动团队最终的目标是接入核心系统 80% 以上的请求,将移动端访问性能提升 30% 以上。相信通过团队的共同努力,不断创新,移动端性能还可以有更大的提升。


作者:任良成、王一硼

编辑:孙淑娟


任良成


苏宁云商 IT 总部架构师

主要承担苏宁易购 https 改造,负责统一接入层上线,在网络性能优化方面有很深的思考和领悟,现正和研发团队一起建设统一接入层,持续优化网关层,做出更高效稳健的网关。


王一硼


苏宁云商 IT 总部高级架构师

拥有多年 IT 平台研发和管理工作经验,先后在苏宁,阿里,惠普等大型互联网和 IT 企业工作,对 SOA 企业架构,高并发高可用的系统设计有多年的实战经验,专注于分布式,高并发,高性能/性能调优,架构拆分和整合,大数据等技术领域。


精彩文章推荐:

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存